package testbench;

import graph.GraphFile;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import settings.Global;
import util.BFS;
import util.DFS;

/**
 * Used to run a bunch of tests to collect data for analysis.
 * 
 * @author Jonathan
 * 
 */
public class DataCollector
{

    /**
     * Find a path using BFS several times
     * 
     * @param gf
     *            Graph
     * @param sampleSize
     *            Number of times to run test
     * @param seed
     *            Seed to generate random page
     */
    public static void BFSFindPath(GraphFile gf, int sampleSize, int seed)
    {
	// store stats
	// ArrayList<Long> sizeData = new ArrayList<Long>(sampleSize);
	// ArrayList<Long> times = new ArrayList<Long>(sampleSize);

	// variables used in loop
	Random r = new Random(seed);
	int pageNum1, pageNum2;
	long startTime, endTime;
	LinkedList<Integer> lli;

	// do a loop for data
	for (int i = 0; i < sampleSize; i++)
	{
	    // prevent pages with no incoming links
	    do
	    {
		pageNum1 = r.nextInt(Global.numWikiPages);
	    } while (gf.getOutgoingLinks(pageNum1).size() < Global.linksThreshold);
	    do
	    {
		pageNum2 = r.nextInt(Global.numWikiPages);
	    } while (gf.getOutgoingLinks(pageNum2).size() < Global.linksThreshold);

	    startTime = System.currentTimeMillis(); // begin
	    lli = BFS.findPath(gf, pageNum1, pageNum2);
	    endTime = System.currentTimeMillis(); // end

	    // store data
	    // sizeData.add((long)lli.size());
	    // times.add(endTime-startTime);
	    System.out.println("Path Length: " + lli.size() + ", Time: " + (endTime - startTime));
	}
    }

    /**
     * Runs BFS Traversal a lot of times
     * 
     * @param gf
     *            Graph
     * @param sampleSize
     *            Number of times to run test
     * @param seed
     *            Seed for random page
     */
    public static void BFSTraversal(GraphFile gf, int sampleSize, int seed)
    {
	// store stats
	// ArrayList<Long> sizeData = new ArrayList<Long>(sampleSize);
	// ArrayList<Long> times = new ArrayList<Long>(sampleSize);

	// variables used in loop
	Random r = new Random(seed);
	int pageNum1, pageNum2;
	long startTime, endTime;
	int size;

	// do a loop for data
	for (int i = 0; i < sampleSize; i++)
	{
	    // prevent pages with no incoming links
	    do
	    {
		pageNum1 = r.nextInt(Global.numWikiPages);
	    } while (gf.getOutgoingLinks(pageNum1).size() < Global.linksThreshold);
	    do
	    {
		pageNum2 = r.nextInt(Global.numWikiPages);
	    } while (gf.getOutgoingLinks(pageNum2).size() < Global.linksThreshold);

	    startTime = System.currentTimeMillis(); // begin
	    size = BFS.traverse(gf, pageNum1);
	    endTime = System.currentTimeMillis(); // end

	    // store data
	    // sizeData.add((long)size);
	    // times.add(endTime-startTime);
	    System.out.println("Pages Reached: " + size + ", Time: " + (endTime - startTime));
	}
    }

    /**
     * Compares DFS and BFS N levels
     * 
     * @param gf
     *            Graph
     * @param sampleSize
     *            Number of times to run test
     * @param seed
     *            Seed for randomness
     */
    public static void BFSDFSNLevels(GraphFile gf, int sampleSize, int seed)
    {
	// variables used in loop
	Random r = new Random(seed);
	int pageNum1, levels;
	long startTime1, endTime1, startTime2, endTime2;
	int size;
	List<Integer> BFSLevels, DFSLevels;

	// do a loop for data
	for (int i = 0; i < sampleSize; i++)
	{
	    // prevent pages with no incoming links
	    do
	    {
		pageNum1 = r.nextInt(Global.numWikiPages);
	    } while (gf.getOutgoingLinks(pageNum1).size() < Global.linksThreshold);
	    levels = r.nextInt(3) + 1;

	    startTime1 = System.currentTimeMillis(); // begin
	    BFSLevels = BFS.traverseNLevels(gf, pageNum1, levels);
	    endTime1 = System.currentTimeMillis(); // end

	    startTime2 = System.currentTimeMillis(); // begin
	    DFSLevels = DFS.traverseNLevels(gf, pageNum1, levels);
	    endTime2 = System.currentTimeMillis(); // end

	    // store data
	    System.out.println("Levels: " + levels + ", BFS Size: " + BFSLevels.size() + ", DFS Size: " + DFSLevels.size() + ", BFS Time: " + (endTime1 - startTime1) + ", DFS Time: " + (endTime2 - startTime2));
	}
    }
}
